<?php


namespace App\Http\Controllers\User;


use App\Http\Controllers\Controller;
use App\Services\MemberService;
use EasyWeChat\Factory;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Http\Request;

/**
 * 微信公众号
 * Class WechatController
 * @package App\Http\Controllers\User
 */
class WechatController extends Controller
{
    // 自动回复内容
    const AUTO_RES = [

    ];


    // 默认回复消息
    const DEFAULT_MSG = <<<EOF
欢迎关注“L3Y乐享游”官方公众号.

-------------------------------------
1.官方 QQ群号：游戏内查询
-------------------------------------
2.更多游戏版本： <a href="https://l3y.cn/">L3Y.cn</a>
-------------------------------------
3.福利多多（电脑端登录）
L3Y.cn  可领取每日福利
-------------------------------------
EOF;




    public function init()
    {
        //         制定允许其他域名访问
        header("Access-Control-Allow-Origin:*");
        // 响应类型
        header('Access-Control-Allow-Methods:POST');
        // 响应头设置
        header('Access-Control-Allow-Headers:x-requested-with, content-type, Authorization');
    }

    public function server()
    {

        try{
            $config = config('wechat');

            $app = Factory::officialAccount($config);
            $app->server->push(function ($message) use ($app) {
                Log::info($message);
                // $message['FromUserName'] // 用户的 openid
                // $message['MsgType'] // 消息类型：event, text....
                switch ($message['MsgType']) {
                    case 'event':
                        // Event 事件类型 （如：subscribe(订阅)、unsubscribe(取消订阅) ...， CLICK 等）
                        $openId = $message['FromUserName'];
                        $qrKey = $message['EventKey']; // 二维码对应的值
                        switch ($message['Event']) {
                            case 'subscribe':
                                // 关注事件
                                if ($this->checkIsBind($qrKey)) {
                                    return $this->bindUser($app, $openId, $this->getFromIdByCodeKey($qrKey));
                                }
                                if ($this->checkIsBindCustomService($qrKey)) {
                                    return $this->bindCustomService($app, $openId, $this->getCustomServiceCodeKey($qrKey));
                                }

                                if ($qrKey) {
                                    // 未关注直接扫码的key值
                                    $qrKey = substr($qrKey, 8);
                                }

                                $uid = $this->createUser($app, $openId);
                                Redis::set($qrKey, $uid);
                                //cache()->put($qrKey, $uid, 300); // 设置对应的key为登录成功状态
                                $this->sendLoginNotify($qrKey, $message);
                                return '登录成功';
                            case 'unsubscribe':
                                Log::info('取消事件');
                                break;
                            case 'SCAN':
                                if ($this->checkIsBind($qrKey)) {
                                    return $this->bindUser($app, $openId, $this->getFromIdByCodeKey($qrKey));
                                }
                                if ($this->checkIsBindCustomService($qrKey)) {
                                    return $this->bindCustomService($app, $openId, $this->getCustomServiceCodeKey($qrKey));
                                }
                                $uid = $this->createUser($app, $openId);
                                Redis::set($qrKey, $uid);
                                $this->sendLoginNotify($qrKey, $message);
                                //cache()->put($qrKey, $uid, 300); // 设置对应的key为登录成功状态
                                return '登录成功';
                            case 'CLICK':
                                // 菜单点击事件
                                switch ($message['EventKey']) {
                                    case 'LB_CODE':
                                        return self::DEFAULT_MSG;
                                    case 'CUS_SER':
                                        return '请进入官网右下角联系客服QQ或微信';
                                }
                            default:
                        }

                        break;
                    default:
                        if (key_exists($message['Content'], self::AUTO_RES)) {
                            return self::AUTO_RES[$message['Content']];
                        }
                        return self::DEFAULT_MSG;
                        break;
                }
            });
            return $app->server->serve();
        }catch (\Exception $e){
            Log::info($e->getMessage(), $e->getFile(),$e->getLine());
        }
    }

    private function checkIsBind($key)
    {
        $prefix = 'bind';
        return strncmp($key, $prefix, strlen($prefix)) === 0;
    }

    private function checkIsBindCustomService($key)
    {
        $prefix = 'ctmSer';
        return strncmp($key, $prefix, strlen($prefix)) === 0;
    }

    /**
     * 获取邀请人
     * @param $key
     * @return string|string[]
     */
    private function getFromIdByCodeKey($key)
    {
        // bind_***
        return str_replace('bind_', '', $key);
    }

    /**
     * 获取客服
     * @param $key
     * @return string|string[]
     */
    private function getCustomServiceCodeKey($key)
    {
        // bind_***
        return str_replace('ctmSer_', '', $key);
    }

    private function bindUser(\EasyWeChat\OfficialAccount\Application $app, $openId, $fromId)
    {
        // 判断openid是否存在
        $userInfo = $app->user->get($openId);
        $user = DB::table('users')->where('unionid', $userInfo['unionid'])->first();
        if ($user) {
            return '您已经是老用户了';
        }
        $date = date('Y-m-d H:i:s');
        $uid = DB::table('users')->insertGetId([
            'username' => $userInfo['nickname'],
            'wx_unionid' => $openId,
            'created_at' => $date,
            'updated_at' => $date,
            'unionid' => $userInfo['unionid'],
            'from_id' => $fromId,
            'birthday' => '1970-01-01'
        ]);
        if (!$uid) {
            return '绑定失败';
        }
        return '绑定成功';
    }

    /**
     * 绑定客服
     * @param \EasyWeChat\OfficialAccount\Application $app
     * @param $openId
     * @param $adminId
     * @return \Illuminate\Http\JsonResponse|string
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    private function bindCustomService(\EasyWeChat\OfficialAccount\Application $app, $openId, $adminId)
    {
        $ctmSer = DB::table('customer_service')->first();
        if (!$ctmSer) {
            return '客服信息错误';
        }
        // 判断openid是否存在
        $userInfo = $app->user->get($openId);
        $user = DB::table('users')->where('unionid', $userInfo['unionid'])->first();
        if (!$user) {
            $date = date('Y-m-d H:i:s');
            $uid = DB::table('users')->insertGetId([
                'username' => $userInfo['nickname'],
                'wx_unionid' => $openId,
                'created_at' => $date,
                'updated_at' => $date,
                'unionid' => $userInfo['unionid'],
                'from_id' => 0,
                'level_id' => 1,
                'birthday' => '1970-01-01'
            ]);
        } else {
            $uid = $user->id;
        }
        if (!$uid) {
            return '用户注册失败';
        }
        try {
            MemberService::bindCustomService($userInfo['unionid'], $adminId, 1);
            return '绑定客服成功';
        }catch (\Exception $e) {
            return errorResp($e->getMessage());
        }
    }

    /**
     * 创建用户
     * @param $app
     * @param $openId
     * @return int|mixed
     */
    public function createUser(\EasyWeChat\OfficialAccount\Application $app, $openId)
    {
        // 判断openid是否存在
        $userInfo = $app->user->get($openId);
        $user = DB::table('users')->where('unionid', $userInfo['unionid'])->first();
        if ($user) {
            if (empty($user->wx_unionid) || $user->wx_unionid != $openId) {
                DB::table('users')->where('id', $user->id)->update([
                    'wx_unionid' => $openId
                ]);
            }
            return $user->id;
        }
        $date = date('Y-m-d H:i:s');
        $uid = DB::table('users')->insertGetId([
            'username' => $userInfo['nickname'],
            'wx_unionid' => $openId,
            'created_at' => $date,
            'updated_at' => $date,
            'unionid' => $userInfo['unionid'],
            'birthday' => '1970-01-01'
        ]);
        // 标记新用户
        Redis::set("newUser.id.{$uid}", 'yes');
        // cache()->put("newUser.id.{$uid}", 'yes', 300);
        return $uid;
    }

    /**
     * 获取登录二维码
     * @return \Illuminate\Http\JsonResponse
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function getQrCode()
    {
        header("Access-Control-Allow-Origin:*");
        $config = config('wechat');
        $app = Factory::officialAccount($config);
        $key = time().mt_rand(1000,9999);
        Redis::set($key, 0);
        //cache()->put($key, 0, 3600);
        $result = $app->qrcode->temporary($key, 3600);
        return response()->json(['message' => '', 'success' => 'true', 'data' => $result, 'key' => $key], 200);
    }

    /**
     * 获取登录状态 轮训接口
     * @param $key
     * @return \Illuminate\Http\JsonResponse
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function getLoginStatus($key)
    {
        header("Access-Control-Allow-Origin:*");
        $id = Redis::get($key);
        //$id = cache()->get($key);
        if (is_null($id)) {
            return response()->json(['message' => '请重新获取登录二维码', 'success' => 'reload'], 200);
        }
        if ($id == 0) {
            return response()->json(['message' => '等待登录中', 'success' => 'false'], 200);
        }
        $user = DB::table('users')->find($id);
        Redis::set($key, null);
        //cache()->set($key, null);
        if (!$user) {
            return response()->json(['message' => '请重新获取登录二维码', 'success' => 'false'], 200);
        }
        // 是否新用户
        $isNew = Redis::get("newUser.id.{$id}");
        Redis::set("newUser.id.{$id}", null);
        $token = md5($user->id . time(). uniqid()) . uniqid();
        $update = ['token' => $token];
        $msg = "登录成功";
        $fromId = Cookie::get('from_id', 0);
        if (!$fromId && $user->from_id != 0 ){
            $mes = "用户已被绑定";
        }
        if ($user->from_id == 0 && $isNew == 'yes') {
            //外面传来的

            if (!$fromId) {
                // unionid邀请
                $uid = Cookie::get('from_union_id', 0);
                if ($uid) {
                    $fu = DB::table('users')->where('unionid', $uid)->first();
                    if ($fu) {
                        $fromId = $fu->id;
                    }
                }
            }
            if ($fromId > 0 && $fromId != $user->id) {
                $parentUser = DB::table('users')->find($fromId);
                if ($parentUser) {
                    $update['from_id'] = $fromId;
                }
                $msg = "绑定成功";
                // 发送邀请者奖励
//                $parent = DB::table('users')->find($fromId);
//                if ($parent) {
//                    $reward = 0;//送的充值金额
//                    MemberService::setMemberBalance(
//                        $parent,
//                        MemberService::BalanceTypeLy,
//                        MemberService::FromTypeReward,
//                        $user->id,
//                        $reward,
//                        '好友注册奖励'
//                    );
//                }
            }
        }

        DB::table('users')->where('id', $id)->update($update);
        //cookie('token', $token);
        Cookie::queue('token', $token);
        Cookie::queue('user_id', $id, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = false);
        MemberService::refreshLevel($user);
        // 写入登录记录
        DB::table('user_login_log')->insert(['unionid' => $user->unionid, 'create_time'=>date('Y-m-d H:i:s')]);
        return response()->json(['message' => $msg, 'success' => 'true', 'data' => [
            'id' => $user->id,
            'username' => $user->username,
            'unionid'=>$user->unionid,
        ]], 200);
    }

    /**
     * 是否登录
     * @return \Illuminate\Http\JsonResponse
     */
    public function isLogin()
    {
        return response()->json(['message' => '', 'success' => 'true'], 200);
    }

    // 设置菜单
    public function dasiniyecaibudaocaidan()
    {
        // var_dump(111);die;
        $config = config('wechat');

        $app = Factory::officialAccount($config);
        $buttons = [
            [
                "type" => "click",
                "name" => "领取福利",
                "key"  => "LB_CODE"
            ],
            // [
            //     "type" => "click",
            //     "name" => "联系客服",
            //     "key"  => "LB_CODE"
            // ],
            [
                "type" => "view",
                "name" => "联系客服",
                "url"  => "https://wpa1.qq.com/fDjdoCn4?_type=wpa&qidian=true"
            ],
            [
                "type" => "view",
                "name" => "投诉和建议",
                "url"  => "https://wpa1.qq.com/Zy1pyQmh?_type=wpa&qidian=true"
            ]
            // [
            //     "type" => "click",
            //     "name" => "投诉和建议",
            //     "key"  => "CUS_SER"
            // ]
        ];
        $res = $app->menu->create($buttons);
        dump($res);
    }

    // 第三方用户列表
    const THIRD_LIST = [
        'u1' => [
            'key' => 'u1Key110'
        ],
    ];

    /**
     * 获取登录二维码(第三方)
     * @return \Illuminate\Http\JsonResponse
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function getQrCodeThird(Request $request)
    {
        $notifyUrl = urldecode($request->get('notifyUrl'));
        $sign = $request->get('sign');
        $timestemp = $request->get('timestemp');
        $appid = $request->get('appid');
        if (!$appid || !array_key_exists(THIRD_LIST, $appid)) {
            return response()->json(['message' => 'appid错误', 'success' => 'false'], 200);
        }
        if (!$notifyUrl) {
            return response()->json(['message' => '回调地址不能为空', 'success' => 'false'], 200);
        }
        if (!$sign) {
            return response()->json(['message' => '签名错误', 'success' => 'false'], 200);
        }
        if (!$timestemp || !is_numeric($timestemp)) {
            return response()->json(['message' => '时间戳错误', 'success' => 'false'], 200);
        }
        if (time() - $timestemp > 10) {
            return response()->json(['message' => '请求已过期', 'success' => 'false'], 200);
        }
        // 验签
        $ukey = THIRD_LIST[$appid]['key'];
        if ($sign != md5($timestemp.$ukey)) {
            return response()->json(['message' => '签名错误', 'success' => 'false'], 200);
        }
        $config = config('wechat');
        $app = Factory::officialAccount($config);
        $key = time().mt_rand(1000,9999);
        Redis::setex($key, 600, 0);
        // cache()->set($key, 0, 3600);
        $result = $app->qrcode->temporary($key, 3600);
        // 将回调信息写入redis
        $redisInfo = [
            'url' => $notifyUrl,
        ];
        Redis::setex('third.'.$key, 600, json_encode($redisInfo));
        $data = [
            'key' => $key,
            'result' => $result
        ];
        return response()->json(['message' => '', 'success' => 'true', 'data' => $data], 200);
    }

    // 给第三方发送登录回调
    private function sendLoginNotify($key, $message)
    {
        $redisInfo = Redis::get('third.'.$key);
        if (!$redisInfo) {
            return;
        }
        $redisInfo = json_decode($redisInfo, true);
        $data = [
            'key' => $key,
            'message' => $message,
        ];
        $this->curlPost($redisInfo['url'], $data);
        Redis::set('third.'.$key, null);
    }

    private function curlPost($url,$post_data,$header=[])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        curl_setopt($ch, CURLOPT_HEADER, $header);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }
    
    public function storeUsersInfo()
    {
        // 增加执行时间和内存限制
        set_time_limit(0);
        ini_set('memory_limit', '512M');

        $accessToken = $this->getAccessToken();
        $nextOpenid = request()->get('next_openid', ''); // 从URL参数获取next_openid, 如果没有则为''

        $allUserInfos = []; // 存储所有获取到的用户信息

        do {
            // 获取关注用户的 openid 列表
            $url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={$accessToken}&next_openid={$nextOpenid}";
            $response = file_get_contents($url);
            $data = json_decode($response, true);

            if (isset($data['data']['openid']) && !empty($data['data']['openid'])) {
                $openids = $data['data']['openid'];
                $userInfos = $this->getUserInfosInParallel($openids, $accessToken);

                // 将获取到的用户信息追加到总数组中
                if (!empty($userInfos)) {
                    $allUserInfos = array_merge($allUserInfos, $userInfos);
                }

                // 获取下一个 next_openid
                $nextOpenid = isset($data['next_openid']) ? $data['next_openid'] : '';
            } else {
                // 如果没有获取到 openid 或者已经到达最大限制，终止获取
                $nextOpenid = null;
            }

        } while ($nextOpenid && count($allUserInfos) < 10000); // 限制最多获取10000条数据

        // 批量插入到数据库中，使用事务确保一致性
        if (!empty($allUserInfos)) {
            DB::beginTransaction();
            try {
                DB::table('wechat_users')->insertOrIgnore($allUserInfos);
                DB::commit();
                // Log::info('Transaction succeeded: ' . count($allUserInfos) . ' records inserted.');
            } catch (\Exception $e) {
                DB::rollBack();
                // Log::error('Transaction failed: ' . $e->getMessage());
                return 'Failed to store user info.';
            }
        }

        return 'User info stored successfully';
    }

    private function getUserInfosInParallel($openids, $accessToken)
    {
        $mh = curl_multi_init();
        $curlHandles = [];
        $results = [];

        foreach ($openids as $openid) {
            $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$accessToken}&openid={$openid}&lang=zh_CN";
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_multi_add_handle($mh, $ch);
            $curlHandles[$openid] = $ch;
        }

        do {
            $status = curl_multi_exec($mh, $active);
            if ($active) {
                curl_multi_select($mh);
            }
        } while ($active && $status == CURLM_OK);

        foreach ($curlHandles as $openid => $ch) {
            $response = curl_multi_getcontent($ch);
            $userInfo = json_decode($response, true);

            if (isset($userInfo['unionid'])) {
                $results[] = [
                    'openid' => $openid,
                    'unionid' => $userInfo['unionid'],
                    'nickname' => $userInfo['nickname'],
                    'subscribe_time' => date('Y-m-d H:i:s', $userInfo['subscribe_time']),
                ];
            }

            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }

        curl_multi_close($mh);

        return $results;
    }

    private function getAccessToken()
    {
        $appId = 'wx7f335888b152914a';
        $appSecret = '5847a57474e8941678e9f3967d61c2cb';
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
        $response = file_get_contents($url);
        // dd($response);
        $data = json_decode($response, true);

        return isset($data['access_token']) ? $data['access_token'] : null;
    }
    
    private function getAccessToken1()
    {
        $appId = 'wxc047797ecdf262c4';
        $appSecret = 'e4ec2521d35eb46389c31171c6129caa';
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
        $response = file_get_contents($url);
        // dd($response);
        $data = json_decode($response, true);

        return isset($data['access_token']) ? $data['access_token'] : null;
    }
    
    public function storeAllUsersTo24WeChatUsers()
    {
        // 增加执行时间和内存限制
        set_time_limit(0);
        ini_set('memory_limit', '1024M');

        $accessToken = $this->getAccessToken1();
        $nextOpenid = ''; // 初始 next_openid 为空
        $allUserInfos = []; // 存储所有获取到的用户信息

        do {
            // 获取关注用户的 openid 列表
            $url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={$accessToken}&next_openid={$nextOpenid}";
            $response = file_get_contents($url);
            $data = json_decode($response, true);

            if (isset($data['data']['openid']) && !empty($data['data']['openid'])) {
                $openids = $data['data']['openid'];
                $userInfos = $this->getUserInfosInParallel($openids, $accessToken);

                // 将获取到的用户信息追加到总数组中
                if (!empty($userInfos)) {
                    $allUserInfos = array_merge($allUserInfos, $userInfos);
                }

                // 获取下一个 next_openid
                $nextOpenid = isset($data['next_openid']) ? $data['next_openid'] : null;
            } else {
                $nextOpenid = null; // 没有更多数据
            }

        } while ($nextOpenid && count($allUserInfos) < 10000); // 限制最多获取10000条数据

        // 批量插入到24wechat_users数据库表中，使用事务确保一致性
        if (!empty($allUserInfos)) {
            DB::beginTransaction();
            try {
                DB::table('24wechat_users')->insertOrIgnore($allUserInfos);
                DB::commit();
                return 'User info stored successfully in 24wechat_users table';
            } catch (\Exception $e) {
                DB::rollBack();
                return 'Failed to store user info: ' . $e->getMessage();
            }
        }

        return 'No user info to store';
    }


    
    
    
    
    
    
    
    
    public function findOpenidByUnionid($unionid)
    {
        $accessToken = $this->getAccessToken();
        $nextOpenid = ''; // 初始 next_openid 为空

        do {
            // 获取关注用户的 openid 列表
            $url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={$accessToken}&next_openid={$nextOpenid}";
            $response = Http::get($url);
            $data = $response->json();

            if (isset($data['data']['openid'])) {
                $openids = $data['data']['openid'];

                // 遍历每个 openid 并获取用户详细信息
                foreach ($openids as $openid) {
                    $userInfo = $this->getUserInfo($openid, $accessToken);

                    if (isset($userInfo['unionid']) && $userInfo['unionid'] === $unionid) {
                        return "Found OpenID: " . $openid;
                    }
                }

                // 获取下一个 next_openid
                $nextOpenid = isset($data['next_openid']) ? $data['next_openid'] : null;
            } else {
                $nextOpenid = null;
            }

        } while ($nextOpenid);

        return "No OpenID found for this UnionID.";
    }

    private function getUserInfo($openid, $accessToken)
    {
        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$accessToken}&openid={$openid}&lang=zh_CN";
        $response = Http::get($url);
        return $response->json();
    }
    
    
    
}
